--- modbus模块功能
-- @module modbus
-- @author Dozingfiretruck
-- @license MIT
-- @copyright openLuat
-- @release 2020.12.17
module(..., package.seeall)
require "pins"
require "sys"
require "uart"
require "utils"
require "common"
require "nvm"
require "terminalSendTheme"
require "mqttOutMsgKeson"
require "mqttInMsgKeson"
require "mqttOutMsg"
require "logGenerator"
require "regularlyUploadData"

-- 初始化nvm获取配置参数
nvm.init("config.lua", true)

-- 保持系统处于唤醒状态，此处只是为了测试需要，所以此模块没有地方调用pm.sleep("testUart")休眠，不会进入低功耗休眠状态
-- 在开发“要求功耗低”的项目时，一定要想办法保证pm.wake("modbusrtu")后，在不需要串口时调用pm.sleep("testUart")
pm.wake("modbusrtu")
PressValueConvert, Alarm = 0.00, "0"
-- gpio口初始化
local setGpio16Fnc = pins.setup(pio.P0_16, 1) -- 电磁阀吸合 0-正常 1-吸合
local setGpio17Fnc = pins.setup(pio.P0_17, 1) -- 报警灯 0-灯灭 1-灯亮
local uart_id = 1
local uart_baud = 9600
local doAlarmOrNot, doAlarmCount, resultOfRead, limitAlarmFlag = false, 0, true,
                                                                 false
local Slave_Addr, Instructions, Reg_Encode, Data_Value, timeTaskId
-- 压力传感器对应参数：地址，波特率，压力单位（0-Mpa，1-Kpa，2-Pa，3-Bar，4-mbar，5-kg/cm2，6-psi，7-mh2o，mmh2o）,小数(0-####，1-###.#，
-- 2-##.##，3-#.###),压力值，量程低值，量程高值，滤波值，开关1吸合值，开关1释放值，开关2吸合值，开关2释放值，开关3吸合值，开关3释放值，
-- 开关4吸合值，开关4释放值，ADC实时值
local address, baudRate, pressureUnit, decimalPoint, pressValue, rangeL, rangeH,
      filterValue, ADCRealValue, l_L_LimitAlarm, l_LimitAlarm, h_LimitAlarm,
      h_H_LimitAlarm, lAlarmOrNot, switch1PullIn, switch1ReleaseValue,
      switch2PullIn, switch2ReleaseValue, switch3PullIn, switch3ReleaseValue,
      switch4PullIn, switch4ReleaseValue, manAutoSwitch, delayTime,
      solenoidValveOnOff, dc = nvm.get("Address"), nvm.get("BaudRate"),
                               nvm.get("PressureUnit"), nvm.get("DecimalPoint"),
                               nvm.get("PressValue"), nvm.get("RangeL"),
                               nvm.get("RangeH"), nvm.get("FilterValue"),
                               nvm.get("ADCRealValue"),
                               nvm.get("L_L_LimitAlarm"),
                               nvm.get("L_LimitAlarm"), nvm.get("H_LimitAlarm"),
                               nvm.get("H_H_LimitAlarm"),
                               nvm.get("LAlarmOrNot"), nvm.get("Switch1PullIn"),
                               nvm.get("Switch1ReleaseValue"),
                               nvm.get("Switch2PullIn"),
                               nvm.get("Switch2ReleaseValue"),
                               nvm.get("Switch3PullIn"),
                               nvm.get("Switch3ReleaseValue"),
                               nvm.get("Switch4PullIn"),
                               nvm.get("Switch4ReleaseValue"),
                               nvm.get("ManAutoSwitch"), nvm.get("DelayTime"),
                               nvm.get("solenoidValveOnOff"), nvm.get("Dc")

local sysTime, sendTopic, sendMqttData, alarmNew, abnormalMsg, pressureInfo,
      alarmInfo, alarmInfoLog, pressureTxtCount, alarmTxtCount, logInfo,
      repSendDataCount, uploadTimeControl, uploadNumControl = "", "", "", "0",
                                                              "", "", "", "", 0,
                                                              0, "", 0, 0, 0
local addressGet, baudRateGet, pressureUnitGet, decimalPointGet, pressValueGet,
      rangeLGet, rangeHGet, filterValueGet, ADCRealValueGet, switch1PullInGet,
      l_L_LimitAlarmGet, switch1ReleaseValueGet, switch2PullInGet,
      l_LimitAlarmGet, switch2ReleaseValueGet, switch3PullInGet,
      h_LimitAlarmGet, switch3ReleaseValueGet, switch4PullInGet,
      h_H_LimitAlarmGet, switch4ReleaseValueGet = 0, 0, "", 0, 0, 0, 0, 0, 0, 0,
                                                  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                                                  0
-- 十六进制转十进制
local function hex2Num(strHex)
    -- log.info("strHex", strHex)
    if strHex == "FFFF" then strHex = "0000" end
    local num = tonumber(strHex, 16)
    return num
end
-- 压力单位转换(压力代号转压力单位)
local function mark2Unit(pressureUnitMark)
    local unitTransfer = ""
    if pressureUnitMark == 0 then
        unitTransfer = "Mpa"
    elseif pressureUnitMark == 1 then
        unitTransfer = "Kpa"
    elseif pressureUnitMark == 2 then
        unitTransfer = "Pa"
    elseif pressureUnitMark == 3 then
        unitTransfer = "Bar"
    elseif pressureUnitMark == 4 then
        unitTransfer = "mbar"
    elseif pressureUnitMark == 5 then
        unitTransfer = "kg/cm2"
    elseif pressureUnitMark == 6 then
        unitTransfer = "psi"
    elseif pressureUnitMark == 7 then
        unitTransfer = "mh^2o"
    elseif pressureUnitMark == 8 then
        unitTransfer = "mmh^2o"
    end
    return unitTransfer
end

-- 波特率转换(波特率代号转波特率)
local function mark2baudRate(baudRateMark)
    local baudRateTransfer
    if baudRateMark == 0 then
        baudRateTransfer = 1200
    elseif baudRateMark == 1 then
        baudRateTransfer = 2400
    elseif baudRateMark == 2 then
        baudRateTransfer = 4800
    elseif baudRateMark == 3 then
        baudRateTransfer = 9600
    elseif baudRateMark == 4 then
        baudRateTransfer = 19200
    elseif baudRateMark == 5 then
        baudRateTransfer = 38400
    elseif baudRateMark == 6 then
        baudRateTransfer = 57600
    elseif baudRateMark == 7 then
        baudRateTransfer = 115200
    end
    return baudRateTransfer
end
-- 手动延迟操作
local function manualDelayHandle()
    if solenoidValveOnOff == "1" then
        setGpio16Fnc(1)
        setGpio17Fnc(1)
        if alarmNew == "1" then
            if lAlarmOrNot then
                setGpio17Fnc(0)
                sys.wait(delayTime * 1000)
                setGpio16Fnc(0)
            end
        elseif alarmNew == "4" then
            setGpio17Fnc(0)
            sys.wait(delayTime * 1000)
            log.info("TEST-2")
            setGpio16Fnc(0)
        end
    elseif solenoidValveOnOff == "0" then
        setGpio16Fnc(0)
        setGpio17Fnc(0)
    end
end
-- 压力报警处理函数
local function pressureAlarmHandle()
    -- log.info("压力报警处理函数逻辑开始！")
    sysTime = os.time() .. "000"
    if alarmNew == "1" or alarmNew == "2" then -- 低报低切报警
        lAlarmOrNot = nvm.get("LAlarmOrNot")
        log.info("lAlarmOrNot:", lAlarmOrNot, "typelAlarmOrNot:",
                 type(lAlarmOrNot))
        if lAlarmOrNot then -- 低报低切上传与否开关
            sendTopic, sendMqttData =
                terminalSendTheme.quipmentReal_timeDataAssembly_keson(sysTime,
                                                                      alarmNew)
            mqttOutMsgKeson.insertMsgKeson(sendTopic, sendMqttData, 0)
            sendTopic, sendMqttData =
                terminalSendTheme.quipmentReal_timeDataAssembly(sysTime,
                                                                alarmNew)
            mqttOutMsg.insertMsgUser(sendTopic, sendMqttData, 0)
            if not mqttInMsgKeson.EARTHQUAKEORNOT then
                sendTopic, sendMqttData =
                    terminalSendTheme.pressureCutoffDeviceReportMsg(alarmNew)
                mqttOutMsgKeson.insertMsgKeson(sendTopic, sendMqttData, 0)
            end
        end
    else -- 高报高切报警
        log.info("TEST正常是否！！")
        sendTopic, sendMqttData =
            terminalSendTheme.quipmentReal_timeDataAssembly_keson(sysTime,
                                                                  alarmNew)
        mqttOutMsgKeson.insertMsgKeson(sendTopic, sendMqttData, 0)
        sendTopic, sendMqttData =
            terminalSendTheme.quipmentReal_timeDataAssembly(sysTime, alarmNew)
        mqttOutMsg.insertMsgUser(sendTopic, sendMqttData, 0)
        if not mqttInMsgKeson.EARTHQUAKEORNOT then
            sendTopic, sendMqttData =
                terminalSendTheme.pressureCutoffDeviceReportMsg(alarmNew)
            mqttOutMsgKeson.insertMsgKeson(sendTopic, sendMqttData, 0)
        end
    end
    uploadNumControl = uploadNumControl + 1
    uploadTimeControl = 0

    --[[ if alarmNew == "3" then
            alarmInfoLog = "3"
        elseif alarmNew == "4" then
            alarmInfoLog = "4"
        elseif alarmNew == "2" then
            alarmInfoLog = "2"
        elseif alarmNew == "1" then
            alarmInfoLog = "1"
        end
        if alarmTxtCount > 400 then
            alarmTxtCount = 0
        end
        alarmTxtCount = alarmTxtCount + 1
        alarmInfo = alarmInfo .. "[" .. sysTime .. "]" .. "[设备报警值:]" ..
                        alarmInfoLog .. "\n"
        logGenerator.generateLogTask(alarmInfoLog, "alarm", alarmTxtCount) ]]
end
-- 压力报警切换
local function pressureAlarmSwitch()
    log.info("压力报警切换逻辑开始")
    doAlarmCount = 1
    if alarmNew == "0" then
        log.info("DataUploadTaskStat:", regularlyUploadData.DataUploadTaskStat)
        if regularlyUploadData.DataUploadTaskStat == nil then
            log.info("数据上传任务重启！！")
            regularlyUploadData.realTimeDataUpload(dc)
        end
        if solenoidValveOnOff == "1" then
            log.info("TEST-3", solenoidValveOnOff)
            setGpio16Fnc(1)
            setGpio17Fnc(1)
        elseif solenoidValveOnOff == "0" then
            log.info("TEST-4", solenoidValveOnOff)
            setGpio16Fnc(0)
            setGpio17Fnc(0)
        end
    elseif alarmNew == "1" then
        if lAlarmOrNot then
            if manAutoSwitch == "1" then
                setGpio16Fnc(0)
                setGpio17Fnc(0)
            elseif manAutoSwitch == "0" then
                log.info("DelTime:", delayTime)
                if delayTime == 0 then
                    setGpio17Fnc(0)
                    if solenoidValveOnOff == "1" then
                        log.info("TEST-6", solenoidValveOnOff)
                        setGpio16Fnc(1)
                    elseif solenoidValveOnOff == "0" then
                        log.info("TEST-7", solenoidValveOnOff)
                        setGpio16Fnc(0)
                    end
                elseif delayTime > 0 then
                    sys.taskInit(manualDelayHandle)
                end
            end
        elseif lAlarmOrNot == false then
            regularlyUploadData.realTimeDataUpload(dc)
            setGpio16Fnc(1)
            setGpio17Fnc(1)
        end
    elseif alarmNew == "4" then
        if regularlyUploadData.DataUploadTaskStat == nil then
            regularlyUploadData.realTimeDataUpload(dc)
        end
        if manAutoSwitch == "1" then
            setGpio16Fnc(0)
            setGpio17Fnc(0)
        elseif manAutoSwitch == "0" then
            if delayTime == 0 then
                setGpio17Fnc(0)
                if solenoidValveOnOff == "1" then
                    log.info("TEST-6", solenoidValveOnOff)
                    setGpio16Fnc(1)
                elseif solenoidValveOnOff == "0" then
                    log.info("TEST-7", solenoidValveOnOff)
                    setGpio16Fnc(0)
                end
            elseif delayTime > 0 then
                sys.taskInit(manualDelayHandle)
            end
        end
    elseif alarmNew == "2" then
        if lAlarmOrNot then
            if solenoidValveOnOff == "1" then
                setGpio17Fnc(0)
                setGpio16Fnc(1)
            elseif solenoidValveOnOff == "0" then
                setGpio16Fnc(0)
                setGpio17Fnc(0)
            end
        elseif lAlarmOrNot == false then
            regularlyUploadData.realTimeDataUpload(dc)
            setGpio17Fnc(1)
            setGpio16Fnc(1)
        end
    elseif alarmNew == "3" then
        if regularlyUploadData.DataUploadTaskStat == nil then
            regularlyUploadData.realTimeDataUpload(dc)
        end
        if solenoidValveOnOff == "1" then
            setGpio17Fnc(0)
            setGpio16Fnc(1)
        elseif solenoidValveOnOff == "0" then
            setGpio16Fnc(0)
            setGpio17Fnc(0)
        end
    end
    doAlarmOrNot = false
    pressureAlarmHandle()
end
--[[
    功能：处理返回所有数据
 ]]
local function handleReturnAll(returnAllData)
    local getDataLen, forLoopLen = 0, 0
    if string.sub(returnAllData, 3, 4) == "03" then
        getDataLen = hex2Num(string.sub(returnAllData, 5, 6)) -- 返回数据长度
        -- log.info("getDataLen:", getDataLen)
        forLoopLen = getDataLen / 2 - 2
        for i = 1, forLoopLen do
            if i == 1 then
                addressGet = hex2Num(string.sub(returnAllData, 7, 10))
                -- log.info("addressGet:", addressGet)
                if addressGet ~= address then
                    nvm.set("Address", addressGet)
                end
            elseif i == 2 then
                baudRateGet = mark2baudRate(hex2Num(
                                                string.sub(returnAllData, 11, 14)))
                -- log.info("baudRateGet:", baudRateGet)
                if baudRateGet ~= baudRate then
                    nvm.set("BaudRate", baudRateGet)
                end
            elseif i == 3 then
                pressureUnitGet = mark2Unit(hex2Num(
                                                string.sub(returnAllData, 15, 18)))
                -- log.info("pressureUnitGet:", pressureUnitGet)
                if pressureUnitGet ~= pressureUnit then
                    nvm.set("PressureUnit", pressureUnitGet)
                end
            elseif i == 4 then
                decimalPointGet = hex2Num(string.sub(returnAllData, 19, 22))
                -- log.info("decimalPointGet:", decimalPointGet)
                if decimalPointGet ~= decimalPoint then
                    nvm.set("DecimalPoint", decimalPointGet)
                end
            elseif i == 5 then
                pressValueGet = hex2Num(string.sub(returnAllData, 23, 26))
                -- log.info("pressValueGet:", pressValueGet)
                if string.len(pressValueGet) > 0 and pressValueGet then
                    if pressValueGet < 10000 then
                        --[[ if pressValueGet ~= pressValue then
                            nvm.set("PressValue", pressValueGet)
                        end ]]
                        decimalPoint = nvm.get("DecimalPoint")
                        PressValueConvert = pressValueGet / 10 ^ decimalPoint
                    end
                    -- log.info("PressValueConvert：", PressValueConvert)
                    if PressValueConvert >= h_LimitAlarm and PressValueConvert <
                        h_H_LimitAlarm then alarmNew = "3" end
                    if PressValueConvert >= h_H_LimitAlarm then
                        alarmNew = "4"
                    end
                    if PressValueConvert > l_L_LimitAlarm and PressValueConvert <=
                        l_LimitAlarm then alarmNew = "2" end
                    if PressValueConvert <= l_L_LimitAlarm then
                        alarmNew = "1"
                    end
                    if PressValueConvert > l_LimitAlarm and PressValueConvert <
                        h_LimitAlarm then alarmNew = "0" end

                    if Alarm ~= alarmNew then
                        uploadTimeControl = 0
                        uploadNumControl = 0
                        Alarm = alarmNew
                        doAlarmOrNot = true
                    end
                    if doAlarmOrNot or doAlarmCount == 0 then
                        pressureAlarmSwitch()
                    end
                    if not doAlarmOrNot and doAlarmCount ~= 0 and alarmNew ~=
                        "0" then
                        if uploadNumControl < 10 then
                            if uploadTimeControl == 4 then
                                pressureAlarmHandle()
                            end
                            uploadTimeControl = uploadTimeControl + 1
                        end
                    end
                end
            elseif i == 6 then
                rangeLGet = hex2Num(string.sub(returnAllData, 27, 30))
                -- log.info("rangeLGet:", rangeLGet)
                rangeLGet = rangeLGet / (10 ^ decimalPointGet)
                if rangeLGet ~= rangeL then
                    nvm.set("RangeL", rangeLGet)
                end
            elseif i == 7 then
                rangeHGet = hex2Num(string.sub(returnAllData, 31, 34))
                -- log.info("rangeHGet:", rangeHGet)
                rangeHGet = rangeHGet / (10 ^ decimalPointGet)
                if rangeHGet ~= rangeH then
                    nvm.set("RangeH", rangeHGet)
                end
            elseif i == 8 then
                filterValueGet = hex2Num(string.sub(returnAllData, 35, 38))
                -- log.info("filterValueGet:", filterValueGet)
                if filterValueGet ~= filterValue then
                    nvm.set("FilterValue", filterValueGet)
                end
            elseif i == 9 then
                switch1PullInGet = hex2Num(string.sub(returnAllData, 39, 42))
                -- log.info("switch1PullInGet:", switch1PullInGet)
                l_L_LimitAlarmGet = switch1PullInGet / (10 ^ decimalPointGet)
                if l_L_LimitAlarmGet ~= l_L_LimitAlarm then
                    limitAlarmFlag = true
                    nvm.set("L_L_LimitAlarm", l_L_LimitAlarmGet)
                end
                if switch1PullInGet ~= switch1PullIn then
                    limitAlarmFlag = true
                    nvm.set("Switch1PullIn", switch1PullInGet)
                end
            elseif i == 10 then
                switch1ReleaseValueGet = hex2Num(
                                             string.sub(returnAllData, 43, 46))
                -- log.info("switch1ReleaseValueGet:", switch1ReleaseValueGet)
                if switch1ReleaseValueGet ~= switch1ReleaseValue then
                    limitAlarmFlag = true
                    nvm.set("Switch1ReleaseValue", switch1ReleaseValueGet)
                end
            elseif i == 11 then
                switch2PullInGet = hex2Num(string.sub(returnAllData, 47, 50))
                -- log.info("switch2PullInGet:", switch2PullInGet)
                l_LimitAlarmGet = switch2PullInGet / (10 ^ decimalPointGet)
                if l_LimitAlarmGet ~= l_LimitAlarm then
                    limitAlarmFlag = true
                    nvm.set("L_LimitAlarm", l_LimitAlarmGet)
                end
                if switch2PullInGet ~= switch2PullIn then
                    limitAlarmFlag = true
                    nvm.set("Switch2PullIn", switch2PullInGet)
                end
            elseif i == 12 then
                switch2ReleaseValueGet = hex2Num(
                                             string.sub(returnAllData, 51, 54))
                -- log.info("switch2ReleaseValueGet:", switch2ReleaseValueGet)
                if switch2ReleaseValueGet ~= switch2ReleaseValue then
                    limitAlarmFlag = true
                    nvm.set("Switch2ReleaseValue", switch2ReleaseValueGet)
                end
            elseif i == 13 then
                switch3PullInGet = hex2Num(string.sub(returnAllData, 55, 58))
                -- log.info("switch3PullInGet:", switch3PullInGet)
                h_LimitAlarmGet = switch3PullInGet / (10 * decimalPointGet)
                if h_LimitAlarmGet ~= h_LimitAlarm then
                    limitAlarmFlag = true
                    nvm.set("H_LimitAlarm", h_LimitAlarmGet)
                end
                if switch3PullInGet ~= switch3PullIn then
                    limitAlarmFlag = true
                    nvm.set("Switch3PullIn", switch3PullInGet)
                end
            elseif i == 14 then
                switch3ReleaseValueGet = hex2Num(
                                             string.sub(returnAllData, 59, 62))
                -- log.info("switch3ReleaseValueGet:", switch3ReleaseValueGet)
                if switch3ReleaseValueGet ~= switch3ReleaseValue then
                    limitAlarmFlag = true
                    nvm.set("Switch3ReleaseValue", switch3ReleaseValueGet)
                end
            elseif i == 15 then
                switch4PullInGet = hex2Num(string.sub(returnAllData, 63, 66))
                -- log.info("switch4PullInGet:", switch4PullInGet)
                h_H_LimitAlarmGet = switch4PullInGet / (10 ^ decimalPointGet)
                if h_H_LimitAlarmGet ~= h_H_LimitAlarm then
                    limitAlarmFlag = true
                    nvm.set("H_H_LimitAlarm", h_H_LimitAlarmGet)
                end
                if switch4PullInGet ~= switch4PullIn then
                    limitAlarmFlag = true
                    nvm.set("Switch4PullIn", switch4PullInGet)
                end
            elseif i == 16 then
                switch4ReleaseValueGet = hex2Num(
                                             string.sub(returnAllData, 67, 70))
                -- log.info("switch4ReleaseValueGet:", switch4ReleaseValueGet)
                if switch4ReleaseValue ~= switch4ReleaseValueGet then
                    nvm.set("Switch4ReleaseValue", switch4ReleaseValueGet)
                end
            elseif i == 17 then
            end
        end

    end
    if limitAlarmFlag then
        limitAlarmFlag = false
        sys.restart("报警阈值发生改变，重启保存阈值的更改！")
    end
end
--[[
    功能：返回压力值数据的处理
 ]]
local function handleReturnPress(returnPressData)
    pressValueGet = hex2Num(string.sub(returnPressData, 7, 10))
    if string.len(pressValue) > 0 and pressValue then
        PressValueConvert = pressValueGet / 10 ^ decimalPoint
        if PressValueConvert <= 1000 then
            sysTime = os.time() .. "000"
            --[[ if pressureTxtCount > 1000 then
                                    pressureTxtCount = 0
                                end
                                pressureTxtCount = pressureTxtCount + 1
                                pressureInfo = pressureInfo .. "[" .. sysTime .. "]" ..
                                                   "[设备实时压力值:]" .. pressValueConvertGet .. "kPa\n"
                                logGenerator.generateLogTask(pressureInfo, "pressure", pressureTxtCount) ]]
            -- log.info("pressValueConvertGet", PressValueConvert, "h_LimitAlarm",h_LimitAlarm)
            -- log.info("pressValueConvertGet >= h_H_LimitAlarm",PressValueConvert >= h_H_LimitAlarm)
            if pressValueGet < 10000 then
                --[[ if pressValueGet ~= pressValue then
                            nvm.set("PressValue", pressValueGet)
                        end ]]
                decimalPoint = nvm.get("DecimalPoint")
                -- log.info("decimalPoint:", decimalPoint)
                PressValueConvert = pressValueGet / 10 ^ decimalPoint
            end
            if PressValueConvert >= h_LimitAlarm and PressValueConvert <
                h_H_LimitAlarm then alarmNew = "3" end
            if PressValueConvert >= h_H_LimitAlarm then
                alarmNew = "4"
            end
            if PressValueConvert > l_L_LimitAlarm and PressValueConvert <=
                l_LimitAlarm then alarmNew = "2" end
            if PressValueConvert <= l_L_LimitAlarm then
                alarmNew = "1"
            end
            if PressValueConvert > l_LimitAlarm and PressValueConvert <
                h_LimitAlarm then alarmNew = "0" end
            if Alarm ~= alarmNew then
                uploadTimeControl = 0
                uploadNumControl = 0
                Alarm = alarmNew
                doAlarmOrNot = true
            end
            if doAlarmOrNot or doAlarmCount == 0 then
                pressureAlarmSwitch()
            end
            if not doAlarmOrNot and doAlarmCount ~= 0 and alarmNew ~= "0" then
                if uploadNumControl < 10 then
                    if uploadTimeControl == 4 then
                        pressureAlarmHandle()
                    end
                    uploadTimeControl = uploadTimeControl + 1
                end
            end
        end
    end
end
--[[
    功能：处理设备返回的读数据
 ]]
local function handleReturnReadData(returnData)
    -- log.info("Instructions:", Instructions)
    if Reg_Encode == "0x0000" and Data_Value == "0x0013" then -- 所有数据返回处理逻辑
        handleReturnAll(returnData)
    elseif Reg_Encode == "0x0004" and Data_Value == "0x0001" then -- 实时压力返回处理逻辑
        if string.len(string.sub(returnData, 7, 10)) > 0 then -- 返回压力值不为空
            handleReturnPress(returnData)
        end
    end
    -- 返回异常处理
    if string.sub(returnData, 3, 4) == "80" and string.sub(returnData, 5, 6) ==
        "03" then
        if string.sub(returnData, 7, 8) == "01" then
            abnormalMsg = "读命令异常:非法功能"
        elseif string.sub(returnData, 7, 8) == "02" then
            abnormalMsg = "读命令异常:非法数据地址"
        elseif string.sub(returnData, 7, 8) == "03" then
            abnormalMsg = "读命令异常:非法数据"
        end
    end
end
--[[
    功能：处理返回的写数据
 ]]
local function handleReturnWriteData(returnWriteData)
    log.info("Reg_Encode", Reg_Encode, "Data_Value", Data_Value)
    log.info("modbus_read2!")
    local paramValue
    if string.sub(returnWriteData, 3, 4) == "80" and
        string.sub(returnWriteData, 5, 6) == "06" then
        if string.sub(returnWriteData, 7, 8) == "01" then
            abnormalMsg = "写命令异常:非法功能"
        elseif string.sub(a, 7, 8) == "02" then
            abnormalMsg = "写命令异常:非法数据地址"
        elseif string.sub(a, 7, 8) == "03" then
            abnormalMsg = "写命令异常:非法数据"
        end
    else
        log.info("modbus_read3!")
        paramValue = hex2Num(string.sub(returnWriteData, 9, 12))
        log.info("modbus_read3Data:", paramValue)
    end
    log.info("身份判别:", string.sub(returnWriteData, 5, 8))
    if string.sub(returnWriteData, 5, 8) == "0000" then -- 从机地址
        nvm.set("Address", paramValue)
    elseif string.sub(returnWriteData, 5, 8) == "0001" then -- 波特率
        log.info("波特率:", paramValue)
        nvm.set("BaudRate", paramValue)
    elseif string.sub(returnWriteData, 5, 8) == "0002" then -- 压力单位
        nvm.set("PressureUnit", mark2Unit(paramValue))
    elseif string.sub(returnWriteData, 5, 8) == "0003" then -- 小数点
        nvm.set("DecimalPoint", paramValue)
    elseif string.sub(returnWriteData, 5, 8) == "0005" then -- 量程零点
        decimalPoint = nvm.get("DecimalPoint")
        log.info("量程零点！！！")
        nvm.set("RangeL", paramValue / 10 ^ decimalPoint)
    elseif string.sub(returnWriteData, 5, 8) == "0006" then -- 量程满点
        log.info("量程满点！！！")
        decimalPoint = nvm.get("DecimalPoint")
        nvm.set("RangeH", paramValue / 10 ^ decimalPoint)
    elseif string.sub(returnWriteData, 5, 8) == "0007" then -- 滤波值
        nvm.set("FilterValue", paramValue)
    elseif string.sub(returnWriteData, 5, 8) == "0008" then -- 继电器1吸合值
        log.info("低低吸合值！！！", paramValue / 10)
        -- nvm.set("L_L_LimitAlarm", paramValue / 10)
    elseif string.sub(returnWriteData, 5, 8) == "0009" then -- 继电器1释放值
        log.info("低低值！！！", paramValue)
    elseif string.sub(returnWriteData, 5, 8) == "000A" then -- 继电器2吸合值
        log.info("低吸合值！！！", paramValue / 10)
        -- nvm.set("L_LimitAlarm", paramValue / 10)
    elseif string.sub(returnWriteData, 5, 8) == "000B" then -- 继电器2释放值
        log.info("低值！！！", paramValue)
    elseif string.sub(returnWriteData, 5, 8) == "000C" then -- 继电器3吸合值
        log.info("高值！！！", paramValue)
        -- nvm.set("H_LimitAlarm", paramValue / 10)
    elseif string.sub(returnWriteData, 5, 8) == "000D" then -- 继电器3释放值
        log.info("高值释放值！！！", paramValue / 10)
    elseif string.sub(returnWriteData, 5, 8) == "000E" then -- 继电器4吸合值
        log.info("高高值！！！", paramValue)
        -- nvm.set("H_H_LimitAlarm", paramValue / 10)
    elseif string.sub(returnWriteData, 5, 8) == "000F" then -- 继电器4释放值
        log.info("高高释放值！！！", paramValue / 10)
    elseif string.sub(returnWriteData, 5, 8) == "0013" then
        log.info("NVM_solenoidValveOnOff", paramValue)
        if paramValue == 128 then
            log.info("存储电磁阀操作结果1")
            -- nvm.set("solenoidValveOnOff", "1")
        elseif paramValue == 136 then
            log.info("存储电磁阀操作结果0")
            -- nvm.set("solenoidValveOnOff", "0")
        end
    elseif string.sub(returnWriteData, 5, 8) == "FFFE" then -- 参数保存
        -- log.info("进入重启设备！")
        -- sys.restart("重启设备，保存设置参数！")
    end
    logInfo = logInfo .. "[" .. sysTime .. "]" .. "获取设备返回值：" ..
                  "低低值:" .. nvm.get("L_L_LimitAlarm") .. ",低值：" ..
                  nvm.get("L_LimitAlarm") .. ",高值:" ..
                  nvm.get("H_LimitAlarm") .. ",高高值：" ..
                  nvm.get("H_H_LimitAlarm") .. "\n"
    log.info("logInfo:", logInfo)
    logInfo = ""
    -- logGenerator.generateLogTask(logInfo, "sysLog", 0)
end
local function modbus_read()
    local cacheData = ""
    while true do
        local s = uart.read(uart_id, 1)
        -- log.info("S:", s)
        if s == "" then
            if not sys.waitUntil("UART_RECEIVE", 35000 / uart_baud) then
                -- 3.5个字符的时间间隔，只是用在RTU模式下面，因为RTU模式没有开始符和结束符，
                -- 两个数据包之间只能靠时间间隔来区分，Modbus定义在不同的波特率下，间隔时间是不一样的，
                -- 所以就是3.5个字符的时间，波特率高，这个时间间隔就小，波特率低，这个时间间隔相应就大
                -- 4800  = 7.297ms
                -- 9600  = 3.646ms
                -- 19200  = 1.771ms
                -- 38400  = 0.885ms
                -- uart接收数据，如果 35000/uart_baud 毫秒没有收到数据，则打印出来所有已收到的数据，清空数据缓冲区，等待下次数据接收
                -- 注意：
                -- 因为在整个GSM模块软件系统中，软件定时器的精确性无法保证，例如本demo配置的是100毫秒，在系统繁忙时，实际延时可能远远超过100毫秒，达到200毫秒、300毫秒、400毫秒等
                -- 设置的延时时间越短，误差越大
                if cacheData:len() > 0 then

                    solenoidValveOnOff = nvm.get("solenoidValveOnOff")
                    -- log.info("modbus_read1!")
                    local a, _ = string.toHex(cacheData)
                    -- log.info("string.sub(a, 1, 4):", string.sub(a, 1, 4), "a:",a)
                    if string.sub(a, 1, 4) ~= "0103" and string.sub(a, 1, 4) ~=
                        "0106" then
                        -- log.info("resultOfRead 数据错误", resultOfRead)
                        resultOfRead = false
                        break
                    end
                    -- 用户逻辑处理代码
                    -- 获取最新存储数据
                    -- log.info("Instructions:", Instructions)
                    if Instructions == "0x03" then -- 返回读命令数据
                        handleReturnReadData(a)
                    elseif Instructions == "0x06" then -- 写命令返回数据
                        handleReturnWriteData(a)
                    end
                    cacheData = ""
                    resultOfRead = true
                    -- log.info("resultOfRead 数据通讯成功", resultOfRead)
                    break
                else
                    resultOfRead = false
                    log.info("resultOfRead 数据通讯失败", resultOfRead)
                    break
                end
            end
        else
            -- log.info("recive MODBUS MSG1!")
            cacheData = cacheData .. s
        end
    end
    return resultOfRead
end
--[[
--   起始        地址    功能代码    数据    CRC校验    结束
-- 3.5 字符     8 位      8 位    N x 8 位   16 位   3.5 字符
--- 发送modbus数据函数
@function   modbus_send
@param      slaveaddr : 从站地址
            Instructions:功能码
		    reg : 寄存器编号
            value : 写入寄存器值或读取寄存器个数,2字节
@return     无
@usage modbus_send("0x01","0x01","0x0101","0x04")
]]
function Modbus_send(slaveaddr, instructions, reg, value)
    Slave_Addr, Instructions, Reg_Encode, Data_Value = slaveaddr, instructions,
                                                       reg, value
    local modbusSendResult, uartResult
    -- log.info("value", value)
    local data = (string.format("%02x", slaveaddr) ..
                     string.format("%02x", instructions) ..
                     string.format("%04x", reg) .. string.format("%04x", value)):fromHex()
    local modbus_crc_data = pack.pack('<H', crypto.crc16("MODBUS", data))
    local data_tx = data .. modbus_crc_data
    -- log.info("data_tx:", data_tx:toHex())
    uartResult = uart.write(uart_id, data_tx)
    -- log.info("uartResult:", uartResult)
    modbusSendResult = modbus_read()
    -- log.info("modbusSendResult", modbusSendResult)
    if not modbusSendResult then
        while true do
            log.info("data_tx:", data_tx:toHex())
            rtos.sleep(1000)
            uart.write(uart_id, data_tx)
            modbusSendResult = modbus_read()
            log.info("modbusSendResult循环内", modbusSendResult)
            repSendDataCount = repSendDataCount + 1
            if modbusSendResult then
                repSendDataCount = 0
                break
            end
            if repSendDataCount > 2 then
                repSendDataCount = 0
                break
            end
        end
    end
    return modbusSendResult
end

-- 注册串口的数据发送通知函数
uart.on(uart_id, "receive", function() sys.publish("UART_RECEIVE") end)
-- 配置并且打开串口
uart.setup(uart_id, uart_baud, 8, uart.PAR_NONE, uart.STOP_1)
-- 启动串口数据接收任务
-- sys.taskInit(modbus_read)

--[[ sys.taskInit(function ()
    while true do
        sys.wait(5000)
        Slave_Addr,Instructions,Reg_Encode,Data_Value,CRC = "0x01","0x03","0x0000","0x0013","0x0407"
        Modbus_send(Slave_Addr,Instructions,Reg_Encode,Data_Value)
        modbus_read()
    end
end) ]]
